package physics;

import game.Game;
import globals.ObjectFactory;
import globals.ObjectType;

import java.awt.event.ActionEvent;
import java.util.Random;

import physics.Collisions.Collision;
import physics.MovementControl.WalkerMovmentController;
import viewControllers.ViewControllersFactory;
import viewControllers.robot.RobotViewController;

import common.Math3D;
import common.Point3D;

public class Robot extends Weapon {

	Point3D movementVector = new Point3D(0.1,0,0);
	double step = 0.03;
	double rotAngle=0.1;
	double jumpStrength = 0.3;

	boolean hasStoped = false;

	protected int maxDamage = 3;
	protected int damage = 0;

	double hittingRange;
	double radius2 = 1.5;

	public boolean inHittingRange(Point3D pos){
		return (Math3D.subPoint(pos, this.position.getCenter()).norm() <= hittingRange);
	}

	@Override
	public void clockTicked(ActionEvent arg0) {
		if (!hasStoped){ 
			this.getMovementControler().setMovement(Math3D.scalePoint(getFace(),step));
		}
		super.clockTicked(arg0);

	}

	public Robot(){
		hittingRange = 0.6;
		this.setMovementControler(new WalkerMovmentController(this));
		this.getMovementControler().setHasMomentum(true);	
		this.getMovementControler().setMovementLimit(0.05);
		this.getMovementControler().setRotationLimit(0.1);
		this.getMovementControler().setRotationFriction(0.01);

	}

	public void impact(Collision c){
		if (disappearing)
			return;

		GameObject bumpedInto;	
		if (c.getObj1().equals(this))
			bumpedInto= c.getObj2();
		else
			bumpedInto = c.getObj1();


		switch (c.getType()){

		case GRENADE:
			if (((Weapon)bumpedInto).canHit() && inHittingRange(bumpedInto.getCenter())){
				((Weapon)bumpedInto).setCanHit(false);
				if (!((Grenade)bumpedInto).disappearing){
					((Grenade)bumpedInto).explode();
				}
				damage++;
				checkDamage();
			}
			break;

		case MESSILEROBOT:
			if (((Weapon)bumpedInto).canHit() && inHittingRange(bumpedInto.getCenter())){
				((Weapon)bumpedInto).setCanHit(false);


				damage = damage + 5;
				checkDamage();
			}
			break;	
		case AVATARROBOT:	
			rotateTo(bumpedInto);
			if (inHittingRange(bumpedInto.getCenter())){
				//getMovementControler().restoreLastPosition();
				this.getMovementControler().addRotationY(rotAngle);
				this.setMoved(true);
			}
			break;


		}
	}


	protected void rotateTo(GameObject bumpedInto) {


		Point3D targetVector = Math3D.subPoint(bumpedInto.getCenter(), this.getCenter());
		Point3D fixVector =
			Math3D.scalePoint(this.getUp(), 
					Math3D.getDotProduct(targetVector, this.getUp()));
		targetVector.sub(fixVector);
		targetVector.normalize();

		double angle = Math.acos(Math3D.getDotProduct(targetVector, this.getFace()));
		if (Math3D.getDotProduct(targetVector, this.getLeft()) < 0)
			angle = -angle;

		if (!Double.isNaN(angle)){
			this.getMovementControler().rotationY(angle);
		}
	}


	protected void checkDamage() {
		if (this.damage >= this.maxDamage){
			try{
				((RobotViewController)this.getGraphicalObject()).stop();

				hasStoped = true;
				disappearing = true;
				this.setGraphicalObject(ViewControllersFactory.createExplosionViewController(this));
				ticks = 0;
				Random rand = new Random();
				float f = rand.nextFloat();
				if (f<0.2){
					fireCarrot();
				}
				Game.robotDead();}
			catch (Exception e){

			}
		}
	}



	public void fireCarrot(){
		Carrot c = (Carrot)ObjectFactory.createGameObject(ObjectType.CARROT);
		c.setPlanet(planet);
		planet.pinpointToPlanet(c);
		c.getPosition().copy(position);
		c.jump();
	}

	public int getMaxDamage() {
		return maxDamage;
	}

}
